#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "debug.h"
#include "i2c_drv.h"

#define PRINT_LEVEL INFO

#if 0
void i2c_write_bytes(int fd,unsigned char i2c_address ,unsigned char reg_address, unsigned char* data, unsigned short len)
{
    int ret=0;
    unsigned char* write_data = malloc(len + 1);

    write_data[0] = reg_address;
    memcpy(&write_data[1], data, len);

    ret=ioctl(fd, I2C_SLAVE, i2c_address);
    if(ret==-1){
        pr_bug("i2c addrs erro , addrs map is 0-127 : %d \r\n",ret);
    }
    ret=ioctl(fd, I2C_TIMEOUT, 1);
    pr_bug("ret : %d \r\n",ret);
    ret=ioctl(fd, I2C_RETRIES, 1);
    pr_bug("ret : %d \r\n",ret);
    if(write(fd, write_data, len + 1)==-1){
        pr_bug("erro\n");
    }
    else{
        pr_bug("Write data success\n");
    }
    if(write_data != NULL)
    {
        free(write_data);
        write_data = NULL;
    }
}

void i2c_read_bytes(int fd,unsigned char i2c_address , unsigned char reg_address, unsigned char* buf, unsigned short len)
{
    int ret=0;
    ret=ioctl(fd, I2C_SLAVE, i2c_address);
    if(ret==-1){
        pr_bug("i2c addrs erro , addrs map is 0-127 : %d \r\n",ret);
    }
    ioctl(fd, I2C_TIMEOUT, 1);
    ioctl(fd, I2C_RETRIES, 1);

    if(write(fd, &reg_address, 1)==-1){
        pr_bug("erro\n");
    }
    else{
        pr_bug("Write data success\n");
    }

    if(read(fd, buf, len)==-1){
        pr_bug("erro\n");
    }
    else{
        pr_bug("Write data success\n");
    }

    printf("buf[0] = 0x%x\n", buf[0]);

    printf("Read data success\n");
}

#else

void i2c_write_bytes(int fd,unsigned char i2c_address , unsigned char reg_address, unsigned char* data, unsigned short len)
{
    int ret=0;
    struct i2c_rdwr_ioctl_data i2c_write_data;

    i2c_write_data.nmsgs = 1;
    i2c_write_data.msgs = malloc(sizeof(struct i2c_msg) * i2c_write_data.nmsgs);

    i2c_write_data.msgs[0].addr = i2c_address;
    i2c_write_data.msgs[0].flags = 0;
    i2c_write_data.msgs[0].len = len + 1;//address data
    i2c_write_data.msgs[0].buf = malloc(i2c_write_data.msgs[0].len);

    i2c_write_data.msgs[0].buf[0] = reg_address;

    memcpy(&(i2c_write_data.msgs[0].buf[1]), data, (size_t)len);

    // Using ioctl to write data
    ret=ioctl(fd, I2C_RDWR, (unsigned long)&i2c_write_data);
    if(ret==-1){
        pr_warn("Write data erro add reg addr :%d ,maybe i2c addr erro",ret);
    }

    if(i2c_write_data.msgs != NULL)
    {
        free(i2c_write_data.msgs[0].buf);
        free(i2c_write_data.msgs);
        i2c_write_data.msgs = NULL;
    }
}

void i2c_read_bytes(int fd,unsigned char i2c_address , unsigned char reg_address, unsigned char* buf, unsigned short len)
{
    int ret=0;
    struct i2c_rdwr_ioctl_data i2c_read_data;

    i2c_read_data.nmsgs = 2;//Need writing address first, then reading
    i2c_read_data.msgs = malloc(sizeof(struct i2c_msg) * i2c_read_data.nmsgs);

    i2c_read_data.msgs[0].addr = i2c_address;
    i2c_read_data.msgs[0].flags = 0;
    i2c_read_data.msgs[0].len = 1;
    i2c_read_data.msgs[0].buf = malloc(i2c_read_data.msgs[0].len);

    i2c_read_data.msgs[0].buf[0] = reg_address;

    i2c_read_data.msgs[1].addr = i2c_address;
    i2c_read_data.msgs[1].flags = I2C_M_RD;
    i2c_read_data.msgs[1].len = len;
    i2c_read_data.msgs[1].buf = malloc(i2c_read_data.msgs[1].len);
//    i2c_read_data.msgs[1].buf[0] = 0x00;

    // Using ioctl to read data
    ret=ioctl(fd, I2C_RDWR, (unsigned long)&i2c_read_data);
    if(ret==-1){
        pr_warn("read data erro add reg addr :%d ,maybe i2c addr erro",ret);
    }

    pr_db("i2c_read_data.msgs[1].buf[0] = 0x%x\n", i2c_read_data.msgs[1].buf[0]);

    memcpy((void*)buf, (void*)(i2c_read_data.msgs[1].buf), (unsigned int)len);

    if(i2c_read_data.msgs != NULL)
    {
        free(i2c_read_data.msgs[0].buf);
        free(i2c_read_data.msgs[1].buf);
        free(i2c_read_data.msgs);
        i2c_read_data.msgs = NULL;
    }
}

#endif

void i2c_read_bytes_delay(int fd,unsigned char i2c_address , unsigned char reg_address, unsigned char* buf, unsigned short len)
{
    int ret=0;
    struct i2c_rdwr_ioctl_data i2c_read_data;

    i2c_read_data.nmsgs = 1;//Need writing address first, then reading
    i2c_read_data.msgs = malloc(sizeof(struct i2c_msg) * i2c_read_data.nmsgs);

    i2c_read_data.msgs[0].addr = i2c_address;
    i2c_read_data.msgs[0].flags = 0;
    i2c_read_data.msgs[0].len = len;
    i2c_read_data.msgs[0].buf = malloc(len);
    i2c_read_data.msgs[0].buf[0] = reg_address;

    // Using ioctl to read data
    ret=ioctl(fd, I2C_RDWR, (unsigned long)&i2c_read_data);
    if(ret==-1){
        pr_warn("read data erro add reg addr :%d ,maybe i2c addr erro\r\n",ret);
    }

    i2c_read_data.msgs[0].flags = I2C_M_RD;

    // Using ioctl to read data
    ret=ioctl(fd, I2C_RDWR, (unsigned long)&i2c_read_data);
    if(ret==-1){
        pr_warn("read data erro :%d \r\n",ret);
    }

    pr_db("i2c_read_data.msgs[1].buf[0] = 0x%x\n", i2c_read_data.msgs[0].buf[0]);

    memcpy((void*)buf, (void*)(i2c_read_data.msgs[0].buf), (unsigned int)len);

    if(i2c_read_data.msgs != NULL)
    {
        free(i2c_read_data.msgs[0].buf);
        free(i2c_read_data.msgs);
        i2c_read_data.msgs = NULL;
    }
}



